
  <div class="layui-card">
    <div class="layui-card-body">
      <div class="layui-form-item" style="margin-bottom: 15px;">
        <div class="layui-inline">
          <input type="text" id="searchRole" placeholder="搜索角色名称..." class="layui-input" style="width: 250px;">
        </div>
        <div class="layui-inline">
          <button class="layui-btn" id="searchRoleBtn"><i class="layui-icon layui-icon-search"></i> 搜索</button>
          <button class="layui-btn layui-btn-primary" id="refreshRoleBtn"><i class="layui-icon layui-icon-refresh"></i> 刷新</button>
        </div>
        <div class="layui-inline" style="float: right;">
          <button class="layui-btn" id="addRoleBtn"><i class="layui-icon layui-icon-addition"></i> 添加角色</button>
        </div>
      </div>

      <table class="layui-table" lay-skin="line">
        <colgroup>
          <col width="80">
          <col width="200">
          <col>
          <col width="120">
          <col width="180">
          <col width="180">
          <col width="200">
        </colgroup>
        <thead>
          <tr>
            <th>ID</th>
            <th>角色名称</th>
            <th>描述</th>
            <th>权限数量</th>
            <th>创建时间</th>
            <th>最后修改时间</th>
            <th>操作</th>
          </tr>
        </thead>
        <tbody id="roleTable">
        </tbody>
      </table>
    </div>
  </div>

<!-- 角色表单 -->
<script type="text/html" id="roleFormTpl">
  <form class="layui-form" style="padding: 20px;" lay-filter="roleForm">
    <input type="hidden" name="id">
    <div class="layui-form-item">
      <label class="layui-form-label">角色名称</label>
      <div class="layui-input-block">
        <input type="text" name="name" required lay-verify="required" placeholder="请输入角色名称" autocomplete="off" class="layui-input">
      </div>
    </div>
    <div class="layui-form-item layui-form-text">
      <label class="layui-form-label">描述</label>
      <div class="layui-input-block">
        <textarea name="desc" placeholder="请输入角色描述" class="layui-textarea"></textarea>
      </div>
    </div>
    <div class="layui-form-item">
      <label class="layui-form-label">分配权限</label>
      <div class="layui-input-block" id="authListContainer" style="max-height: 400px; overflow-y: auto; border: 1px solid #e6e6e6; padding: 10px; border-radius: 2px;">
        <!-- 权限列表将在这里动态生成 -->
      </div>
    </div>
    <div class="layui-form-item">
      <div class="layui-input-block">
        <button class="layui-btn" lay-submit lay-filter="submitRole">保存</button>
        <button type="reset" class="layui-btn layui-btn-primary">重置</button>
      </div>
    </div>
  </form>
</script>

<style>
  /* 复用auth.html中的64种颜色样式 */
  .auth-color-0 { background-color: #FF6B6B !important; color: white !important; }
  .auth-color-1 { background-color: #4ECDC4 !important; color: white !important; }
  .auth-color-2 { background-color: #45B7D1 !important; color: white !important; }
  .auth-color-3 { background-color: #FFBE0B !important; color: white !important; }
  .auth-color-4 { background-color: #FB5607 !important; color: white !important; }
  .auth-color-5 { background-color: #8338EC !important; color: white !important; }
  .auth-color-6 { background-color: #3A86FF !important; color: white !important; }
  .auth-color-7 { background-color: #38B000 !important; color: white !important; }
  .auth-color-8 { background-color: #9D4EDD !important; color: white !important; }
  .auth-color-9 { background-color: #FF006E !important; color: white !important; }
  .auth-color-10 { background-color: #2EC4B6 !important; color: white !important; }
  .auth-color-11 { background-color: #E71D36 !important; color: white !important; }
  .auth-color-12 { background-color: #662E9B !important; color: white !important; }
  .auth-color-13 { background-color: #43BCCD !important; color: white !important; }
  .auth-color-14 { background-color: #F24236 !important; color: white !important; }
  .auth-color-15 { background-color: #5C9CE6 !important; color: white !important; }
  .auth-color-16 { background-color: #00C1D4 !important; color: white !important; }
  .auth-color-17 { background-color: #FF9F1C !important; color: white !important; }
  .auth-color-18 { background-color: #114B5F !important; color: white !important; }
  .auth-color-19 { background-color: #1A936F !important; color: white !important; }
  .auth-color-20 { background-color: #F45B69 !important; color: white !important; }
  .auth-color-21 { background-color: #2A9D8F !important; color: white !important; }
  .auth-color-22 { background-color: #E9C46A !important; color: black !important; }
  .auth-color-23 { background-color: #F1FAEE !important; color: black !important; }
  .auth-color-24 { background-color: #E63946 !important; color: white !important; }
  .auth-color-25 { background-color: #A8DADC !important; color: black !important; }
  .auth-color-26 { background-color: #1D3557 !important; color: white !important; }
  .auth-color-27 { background-color: #F15BB5 !important; color: white !important; }
  .auth-color-28 { background-color: #9B5DE5 !important; color: white !important; }
  .auth-color-29 { background-color: #00BBF9 !important; color: white !important; }
  .auth-color-30 { background-color: #00F5D4 !important; color: black !important; }
  .auth-color-31 { background-color: #FEE440 !important; color: black !important; }
  .auth-color-32 { background-color: #9B5DE5 !important; color: white !important; }
  .auth-color-33 { background-color: #F15BB5 !important; color: white !important; }
  .auth-color-34 { background-color: #FEE440 !important; color: black !important; }
  .auth-color-35 { background-color: #00BBF9 !important; color: white !important; }
  .auth-color-36 { background-color: #00F5D4 !important; color: black !important; }
  .auth-color-37 { background-color: #9B2226 !important; color: white !important; }
  .auth-color-38 { background-color: #BB3E03 !important; color: white !important; }
  .auth-color-39 { background-color: #AE2012 !important; color: white !important; }
  .auth-color-40 { background-color: #005F73 !important; color: white !important; }
  .auth-color-41 { background-color: #0A9396 !important; color: white !important; }
  .auth-color-42 { background-color: #94D2BD !important; color: black !important; }
  .auth-color-43 { background-color: #E9D8A6 !important; color: black !important; }
  .auth-color-44 { background-color: #CA6702 !important; color: white !important; }
  .auth-color-45 { background-color: #BB3E03 !important; color: white !important; }
  .auth-color-46 { background-color: #AE2012 !important; color: white !important; }
  .auth-color-47 { background-color: #9B2226 !important; color: white !important; }
  .auth-color-48 { background-color: #606C38 !important; color: white !important; }
  .auth-color-49 { background-color: #283618 !important; color: white !important; }
  .auth-color-50 { background-color: #FEFAE0 !important; color: black !important; }
  .auth-color-51 { background-color: #DDA15E !important; color: black !important; }
  .auth-color-52 { background-color: #BC6C25 !important; color: white !important; }
  .auth-color-53 { background-color: #606C38 !important; color: white !important; }
  .auth-color-54 { background-color: #283618 !important; color: white !important; }
  .auth-color-55 { background-color: #FEFAE0 !important; color: black !important; }
  .auth-color-56 { background-color: #DDA15E !important; color: black !important; }
  .auth-color-57 { background-color: #BC6C25 !important; color: white !important; }
  .auth-color-58 { background-color: #264653 !important; color: white !important; }
  .auth-color-59 { background-color: #2A9D8F !important; color: white !important; }
  .auth-color-60 { background-color: #E9C46A !important; color: black !important; }
  .auth-color-61 { background-color: #F4A261 !important; color: black !important; }
  .auth-color-62 { background-color: #E76F51 !important; color: white !important; }
  .auth-color-63 { background-color: #264653 !important; color: white !important; }
  
  .auth-group-header {
    font-weight: bold;
    margin-top: 15px;
    margin-bottom: 10px;
    padding: 8px 10px;
    background-color: #f8f8f8;
    border-left: 3px solid #1E9FFF;
  }
  
  .auth-group-header:first-child {
    margin-top: 5px;
  }
  
  .auth-checkbox-item {
    margin-left: 20px;
    margin-bottom: 8px;
  }
</style>

<script>
// 从后端获取的数据
var roleData = [];       // 角色数据
var authGroupData = [];  // 权限大分类数据
var authData = [];       // 权限组数据
var urisData = [];       // URI权限数据

layui.use(['layer', 'form', 'jquery'], function(){
  var layer = layui.layer;
  var form = layui.form;
  var $ = layui.jquery;
  
  // 格式化时间
  function formatTime(timestamp) {
    if (!timestamp) return '-';
    // 如果是时间戳，转换为格式化时间
    var date = new Date(timestamp);
    return date.getFullYear() + '-' + 
           String(date.getMonth() + 1).padStart(2, '0') + '-' + 
           String(date.getDate()).padStart(2, '0') + ' ' +
           String(date.getHours()).padStart(2, '0') + ':' + 
           String(date.getMinutes()).padStart(2, '0') + ':' + 
           String(date.getSeconds()).padStart(2, '0');
  }
  
  // 获取大分类名称
  function getAuthGroupName(groupID) {
    var group = authGroupData.find(function(g) {
      return g.id === groupID;
    });
    return group ? group.name : '未分类';
  }
  
  // 获取大分类颜色类名
  function getAuthGroupColorClass(groupID) {
    return 'auth-color-' + (groupID % 64);
  }
  
  // 从后端获取数据
  function fetchData() {
    // 显示加载提示
    var loading = layer.load(2);
    
    // 获取权限大分类数据
    fetch('/auth/group')
      .then(response => response.json())
      .then(groupResult => {
        if (groupResult.result) {
          authGroupData = groupResult.data || [];
        }
        
        // 获取权限组数据
        return fetch('/auth/auth');
      })
      .then(response => response.json())
      .then(authResult => {
        if (authResult.result) {
          authData = authResult.data || [];
        }
        
        // 获取URI权限数据
        return fetch('/auth/uris');
      })
      .then(response => response.json())
      .then(urisResult => {
        if (urisResult.result) {
          urisData = urisResult.data || [];
        }
        
        // 获取角色数据
        return fetch('/auth/role');
      })
      .then(response => response.json())
      .then(roleResult => {
        layer.close(loading); // 关闭加载提示
        if (roleResult.result) {
          roleData = roleResult.data || [];
        }
        renderRole();
      })
      .catch(error => {
        layer.close(loading); // 关闭加载提示
        layer.msg('数据加载失败: ' + error.message, {icon: 2});
        console.error('Error:', error);
        // 即使出错也渲染界面，使用现有数据
        renderRole();
      });
  }
  
  // 渲染角色列表
  function renderRole() {
    var tbody = document.getElementById('roleTable');
    tbody.innerHTML = '';
    
    var searchValue = document.getElementById('searchRole').value.toLowerCase();
    var filtered = roleData.filter(function(role) {
      return role.name.toLowerCase().includes(searchValue) ||
             (role.desc && role.desc.toLowerCase().includes(searchValue));
    });
    
    filtered.forEach(function(role) {
      var authList = [];
      try {
        authList = JSON.parse(role.authList || '[]');
      } catch(e) {
        authList = [];
      }
      
      var tr = document.createElement('tr');
      tr.innerHTML = `
        <td><strong>${role.id}</strong></td>
        <td><strong>${role.name}</strong></td>
        <td>${role.desc || '-'}</td>
        <td><span class="layui-badge layui-bg-blue">${authList.length} 个权限</span></td>
        <td>${role.createTime}</td>
        <td>${role.updateTime}</td>
        <td>
          <button class="layui-btn layui-btn-xs layui-btn-normal edit-role" data-id="${role.id}">编辑</button>
          <button class="layui-btn layui-btn-xs layui-btn-danger delete-role" data-id="${role.id}">删除</button>
        </td>
      `;
      tbody.appendChild(tr);
    });
    
    document.querySelectorAll('.edit-role').forEach(function(btn) {
      btn.onclick = function() {
        var id = parseInt(this.getAttribute('data-id'));
        editRole(id);
      };
    });
    
    document.querySelectorAll('.delete-role').forEach(function(btn) {
      btn.onclick = function() {
        var id = parseInt(this.getAttribute('data-id'));
        deleteRole(id);
      };
    });
  }
  
  // 渲染权限选择列表
  function renderAuthList(selectedAuthIds) {
    var container = document.getElementById('authListContainer');
    if (!container) return;
    
    container.innerHTML = '';
    
    // 按权限分类分组
    var groupedAuth = {};
    authData.forEach(function(auth) {
      if (!groupedAuth[auth.groupID]) {
        groupedAuth[auth.groupID] = [];
      }
      groupedAuth[auth.groupID].push(auth);
    });
    
    // 按分类排序渲染
    authGroupData.forEach(function(group) {
      if (!groupedAuth[group.id] || groupedAuth[group.id].length === 0) {
        return;
      }
      
      // 创建分类标题
      var groupDiv = document.createElement('div');
      groupDiv.className = 'auth-group-header';
      groupDiv.innerHTML = `<span class="layui-badge ${getAuthGroupColorClass(group.id)}">${group.name}</span> (${groupedAuth[group.id].length}个权限)`;
      container.appendChild(groupDiv);
      
      // 创建该分类下的权限复选框
      groupedAuth[group.id].forEach(function(auth) {
        var isChecked = selectedAuthIds.indexOf(auth.id) !== -1;
        var checkboxDiv = document.createElement('div');
        checkboxDiv.className = 'auth-checkbox-item';
        checkboxDiv.innerHTML = `
          <input type="checkbox" name="authList[]" value="${auth.id}" title="${auth.name}" ${isChecked ? 'checked' : ''} lay-skin="primary">
        `;
        container.appendChild(checkboxDiv);
      });
    });
    
    // 重新渲染表单
    form.render('checkbox');
  }
  
  // 添加角色
  function addRole() {
    layer.open({
      type: 1,
      title: '添加角色',
      area: ['680px', '750px'],
      content: document.getElementById('roleFormTpl').innerHTML,
      success: function(layero, index) {
        // 修改表单提交按钮的 filter 为唯一值
        var uniqueFilter = 'submitRole-add-' + index;
        layero.find('button[lay-filter="submitRole"]').attr('lay-filter', uniqueFilter);
        
        // 确保表单渲染完成后再设置值
        setTimeout(function() {
          form.val('roleForm', {
            id: '',
            name: '',
            desc: ''
          });
          
          // 渲染权限列表
          renderAuthList([]);
          
          // 重新渲染表单
          form.render();
        }, 100);
        
        // 在 success 回调中直接注册事件，使用唯一的 filter
        form.on('submit(' + uniqueFilter + ')', function(data) {
          // 收集选中的权限ID
          var selectedAuthIds = [];
          var checkboxes = layero[0].querySelectorAll('input[name="authList[]"]:checked');
          for (var i = 0; i < checkboxes.length; i++) {
            selectedAuthIds.push(parseInt(checkboxes[i].value));
          }
          
          // 提交新增到后端
          var loading = layer.load(2);
          
          // 准备提交数据
          var submitData = {
            name: data.field.name,
            desc: data.field.desc,
            authList: JSON.stringify(selectedAuthIds)
          };
          
          // 发送POST请求添加角色
          fetch('/auth/role', {
            method: 'POST',
            headers: {
              'Content-Type': 'application/json'
            },
            body: JSON.stringify(submitData)
          })
          .then(response => {
            const contentType = response.headers.get('content-type');
            if (contentType && contentType.includes('application/json')) {
              return response.json();
            } else {
              throw new Error('服务器返回了非JSON格式的响应: ' + response.status + ' ' + response.statusText);
            }
          })
          .then(result => {
            layer.close(loading);
            if (result.result) {
              // 重新获取数据
              fetchData();
              layer.close(index);
              layer.msg('角色已添加');
            } else {
              layer.msg('添加失败: ' + (result.message || result.msg || '未知错误'), {icon: 2});
            }
          })
          .catch(error => {
            layer.close(loading);
            layer.msg('请求失败: ' + error.message, {icon: 2});
            console.error('Error:', error);
          });
          
          return false;
        });
      }
    });
  }
  
  // 编辑角色
  function editRole(id) {
    var role = roleData.find(function(r) {
      return r.id === id;
    });
    
    if (!role) {
      layer.msg('角色不存在', {icon: 2});
      return;
    }
    
    layer.open({
      type: 1,
      title: '编辑角色',
      area: ['680px', '750px'],
      content: document.getElementById('roleFormTpl').innerHTML,
      success: function(layero, index) {
        // 修改表单提交按钮的 filter 为唯一值
        var uniqueFilter = 'submitRole-edit-' + index;
        layero.find('button[lay-filter="submitRole"]').attr('lay-filter', uniqueFilter);
        
        // 解析权限列表
        var authList = [];
        try {
          authList = JSON.parse(role.authList || '[]');
        } catch(e) {
          authList = [];
        }
        
        // 使用setTimeout确保DOM完全渲染后再设置表单值
        setTimeout(function() {
          form.val('roleForm', {
            id: role.id,
            name: role.name,
            desc: role.desc
          });
          
          // 渲染权限列表
          renderAuthList(authList);
          
          // 重新渲染表单
          form.render();
        }, 100);
        
        // 在 success 回调中直接注册事件，使用唯一的 filter
        form.on('submit(' + uniqueFilter + ')', function(data) {
          // 收集选中的权限ID
          var selectedAuthIds = [];
          var checkboxes = layero[0].querySelectorAll('input[name="authList[]"]:checked');
          for (var i = 0; i < checkboxes.length; i++) {
            selectedAuthIds.push(parseInt(checkboxes[i].value));
          }
          
          // 提交修改到后端
          var loading = layer.load(2);
          
          // 准备提交数据
          var submitData = {
            id: parseInt(data.field.id),
            name: data.field.name,
            desc: data.field.desc,
            authList: JSON.stringify(selectedAuthIds)
          };
          
          // 发送PUT请求更新角色
          fetch('/auth/role', {
            method: 'PUT',
            headers: {
              'Content-Type': 'application/json'
            },
            body: JSON.stringify(submitData)
          })
          .then(response => {
            const contentType = response.headers.get('content-type');
            if (contentType && contentType.includes('application/json')) {
              return response.json();
            } else {
              throw new Error('服务器返回了非JSON格式的响应: ' + response.status + ' ' + response.statusText);
            }
          })
          .then(result => {
            layer.close(loading);
            if (result.result) {
              // 更新本地数据
              role.name = data.field.name;
              role.desc = data.field.desc;
              role.authList = JSON.stringify(selectedAuthIds);
              role.updateTime = formatTime(new Date());
              
              // 重新渲染
              renderRole();
              layer.close(index);
              layer.msg('角色已更新');
            } else {
              layer.msg('更新失败: ' + (result.message || result.msg || '未知错误'), {icon: 2});
            }
          })
          .catch(error => {
            layer.close(loading);
            layer.msg('请求失败: ' + error.message, {icon: 2});
            console.error('Error:', error);
          });
          
          return false;
        });
      }
    });
  }
  
  // 删除角色
  function deleteRole(id) {
    layer.confirm('确定要删除这个角色吗？', {
      icon: 3,
      title: '删除角色'
    }, function(index) {
      // 提交删除到后端
      var loading = layer.load(2);
      
      // 发送DELETE请求删除角色
      fetch('/auth/role?id=' + id, {
        method: 'DELETE'
      })
      .then(response => {
        const contentType = response.headers.get('content-type');
        if (contentType && contentType.includes('application/json')) {
          return response.json();
        } else {
          throw new Error('服务器返回了非JSON格式的响应: ' + response.status + ' ' + response.statusText);
        }
      })
      .then(result => {
        layer.close(loading);
        if (result.result) {
          roleData = roleData.filter(function(role) {
            return role.id !== id;
          });
          
          renderRole();
          layer.close(index);
          layer.msg('角色已删除');
        } else {
          layer.msg('删除失败: ' + (result.message || result.msg || '未知错误'), {icon: 2});
        }
      })
      .catch(error => {
        layer.close(loading);
        layer.msg('请求失败: ' + error.message, {icon: 2});
        console.error('Error:', error);
      });
    });
  }
  
  // 事件绑定
  document.getElementById('addRoleBtn').onclick = addRole;
  document.getElementById('searchRoleBtn').onclick = renderRole;
  document.getElementById('refreshRoleBtn').onclick = fetchData;
  
  // 初始化
  fetchData();
});
</script>
